import fs from "fs";
import path from "path";
import parser from '@babel/parser';
import traverse from '@babel/traverse';
import { generate } from '@babel/generator';
import * as t from '@babel/types';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import { getPathFileList, formatWithPrettier, baiduTranslatekeyMap } from './utils/util.js'
import BaiduTranslate from "./utils/BaiduTranslate.js"; //引入百度翻译文件
import AliyunTranslate from "./utils/AliyunTranslate.js"; // 引入阿里云翻译文件


// 获取当前模块路径（相当于CommonJS中的__filename和__dirname）
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

/**
 * 递归创建嵌套对象的AST节点
 * @param {object} obj - 要转换的对象
 * @returns {object} AST对象节点
 */
function createObjectNode(obj) {
  const properties = [];
  for (const [key, value] of Object.entries(obj)) {
    let valueNode;
    if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
      valueNode = createObjectNode(value);
    } else if (Array.isArray(value)) {
      valueNode = t.arrayExpression(value.map(item => {
        if (typeof item === 'string') return t.stringLiteral(item);
        if (typeof item === 'number') return t.numericLiteral(item);
        if (typeof item === 'boolean') return t.booleanLiteral(item);
        if (item === null) return t.nullLiteral();
        if (typeof item === 'object') return createObjectNode(item);
        return t.stringLiteral(String(item));
      }));
    } else if (typeof value === 'string') {
      valueNode = t.stringLiteral(value);
    } else if (typeof value === 'number') {
      valueNode = t.numericLiteral(value);
    } else if (typeof value === 'boolean') {
      valueNode = t.booleanLiteral(value);
    } else if (value === null) {
      valueNode = t.nullLiteral();
    } else {
      valueNode = t.stringLiteral(String(value));
    }

    properties.push(t.objectProperty(t.identifier(key), valueNode));
  }
  return t.objectExpression(properties);
}


/**
 * 向const message对象添加新的键值对
 * @param {string} filePath - JS文件路径
 * @param {string} newKey - 要添加的键名
 * @param {any} newValue - 要添加的值
 * @returns {boolean} 是否成功添加
 */
function addPropertyToMessageObject(filePath, patchJson) {
  try {
    // 读取文件内容
    const code = fs.readFileSync(filePath, 'utf8');

    // 解析为AST
    const ast = parser.parse(code, {
      sourceType: 'module',
      plugins: ['jsx', 'classProperties']
    });

    let isModified = false;

    // 遍历AST查找const message对象
    traverse.default(ast, {
      VariableDeclaration(path) {
        // 只处理const声明
        if (path.node.kind === 'const') {
          path.node.declarations.forEach(declaration => {
            // 找到名为message的变量
            if (declaration.id.name === 'message') {
              // 检查是否是对象字面量
              if (t.isObjectExpression(declaration.init)) {
                // 创建新的属性节点
                // 根据值的类型创建不同的字面量节点
                for (const [newKey, newValue] of Object.entries(patchJson)) {
                  let valueNode;
                  if (typeof newValue === 'string') {
                    valueNode = t.stringLiteral(newValue);
                  } else if (typeof newValue === 'number') {
                    valueNode = t.numericLiteral(newValue);
                  } else if (typeof newValue === 'boolean') {
                    valueNode = t.booleanLiteral(newValue);
                  } else if (newValue === null) {
                    valueNode = t.nullLiteral();
                  } else if (typeof newValue === 'object') {
                    // 处理嵌套对象
                    valueNode = createObjectNode(newValue);
                  } else {
                    // 默认转为字符串
                    valueNode = t.stringLiteral(String(newValue));
                  }

                  const newProperty = t.objectProperty(
                    t.identifier(newKey),  // 键名
                    valueNode,             // 值
                    false,                 //  computed (是否是计算属性)
                    false                  //  shorthand (是否是简写形式)
                  );

                  // 检查是否已有相同键名，避免重复添加
                  const hasExistingKey = declaration.init.properties.some(prop =>
                    t.isIdentifier(prop.key) && prop.key.name === newKey
                  );

                  if (!hasExistingKey) {
                    // 添加新属性到对象
                    declaration.init.properties.push(newProperty);
                    isModified = true;
                    console.log(`已向message对象添加键值对: ${newKey}=${JSON.stringify(newValue)}`);
                  } else {
                    console.log(`message对象已存在键名: ${newKey}，跳过添加`);
                  }
                }

              } else {
                console.log('message不是对象字面量，无法添加属性');
              }
            }
          });
        }
      }
    });

    // 如果有修改则保存文件
    if (isModified) {
      // 转换AST为代码
      const { code: modifiedCode } = generate(ast, {
        retainLines: true,
        comments: true,
        jsescOption: {
          minimal: true
        }
      });

      // 备份原始文件
      // const backupPath = `${filePath}.bak`;
      // if (!fs.existsSync(backupPath)) {
      //   fs.writeFileSync(backupPath, code, 'utf8');
      // }

      // 写入修改后的内容
      fs.writeFileSync(filePath, modifiedCode, 'utf8');
      console.log(`文件已更新: ${filePath}`);
    }

    return isModified;
  } catch (error) {
    console.error('修改对象时出错:', error);
    throw error;
  }
}

/**
 * 从JS文件中读取const message变量的值
 * @param {string} filePath - JS文件路径
 * @returns {string|undefined} 变量值，如果不存在则返回undefined
 */
function getConstMessageValue(filePath) {
  try {
    // 1. 读取文件内容
    const code = fs.readFileSync(filePath, 'utf8');
    // 2. 解析代码为AST
    const ast = parser.parse(code, {
      sourceType: 'module',
      plugins: ['jsx', 'classProperties']
    });
    let messageValue = {};
    // 3. 遍历AST查找const message变量
    traverse.default(ast, {
      // 查找变量声明
      VariableDeclaration(path) {
        // 只处理const声明
        if (path.node.kind === 'const') {
          // 遍历声明的变量
          path.node.declarations.forEach(declaration => {
            // 检查变量名是否为message
            if (declaration.id.name === 'message') {
              // 根据不同类型的初始值进行处理
              const properties = declaration.init.properties;
              for (let index = 0; index < properties.length; index++) {
                const node = properties[index];
                messageValue[node.key.name] = node.value.value;
              }
            }
          });
        }
      }
    });

    return messageValue;
  } catch (error) {
    console.error('读取变量时出错:', error);
    throw error;
  }
}





const successlist = [];
const errorlist = [];
const unchangedList = [];
const main = async (config) => {
  const pathConfig = config.patchTranslation;

  let translate = null;
  if (config.engine == 'baidu') {
    translate = new BaiduTranslate(config.baidu);
  } else {
    translate = new AliyunTranslate(config.aliyun);
  }


  const list = getPathFileList(path.resolve(pathConfig.scanPath), pathConfig.source).filter(v => v.suffix === 'js')
  const sourceJson = getConstMessageValue(path.join(pathConfig.scanPath, `${pathConfig.source}.js`))
  for (const item of list) {
    const targetJson = getConstMessageValue(item.path)
    let needTranslate = false;
    let patchJson = {}
    req: for (const key of Object.keys(sourceJson)) {
      if (!Object.hasOwn(targetJson, key)) {
        if (sourceJson[key]) {
          console.log(`${item.name}.${item.suffix} 缺少 ${key},正在补全翻译`);
          try {
            needTranslate = true;
            const result = await translate(sourceJson[key], {
              from: pathConfig.source,
              to: config.engine == 'baidu' ? (baiduTranslatekeyMap[item.name] || item.name) : item.name,
              scene:config.scene
            },config.professionalMode);
            patchJson[key] = result;
          } catch (error) {
            console.error("翻译出错:", error);
            needTranslate = false;
            if (!errorlist.includes(item.name)) errorlist.push(item.name);
            console.log(`${item.name}.${item.suffix} 翻译失败，语种可能不支持`);
            break req;
          }
        }
      }
    }
    if (needTranslate) {

      addPropertyToMessageObject(item.path, patchJson)
      console.log(`${item.name}.${item.suffix} 补全完成`);
      // 使用prettier格式化文件
      successlist.push(item.name);
      await formatWithPrettier(item.path);
    } else {
      unchangedList.push(item.name);
      console.log(`${item.name}.${item.suffix} 无需补全`);
    }
  }
}

export default main;